<!--
 * @Descripttion: 角色管理
 * @version:
 * @Author: 穆宏宇
 * @Date: 2020-09-24 15:49
 * @LastEditors: 穆宏宇
 * @LastEditTime: 2020-11-04 16:21:06
-->
<template>
	<div class="bigDiv">
		<!-- 查询 -->
		<el-form :inline="true" :model="searchData" ref="form">
			<el-row>
				<div class="topNav">
					<el-button icon="el-icon-plus" type="text" @click="insertRoleEvent">新增</el-button>
					<el-button type="text" icon="el-icon-refresh-right" style="float:right;"
						@click="resetForm('form')">重置</el-button>
					<el-button type="text" icon="el-icon-search" @click="onSearch" style="float:right;">查询</el-button>
				</div>
				<div style="margin:0 20px;">
					<el-form-item label="角色名称" style="margin-bottom:0px">
						<el-input v-model="searchData.name" placeholder="请输入角色名称" @change="searchValue"></el-input>
					</el-form-item>
				</div>
			</el-row>
		</el-form>
		<!-- 表格 -->
		<el-table border :data="tableData" :max-height="maxHeightNow" style="margin-top: 20px;">
			<el-table-column prop="name" label="角色名称" align="center"></el-table-column>
			<el-table-column prop="describe" label="角色描述" align="center"></el-table-column>
			<!--      <el-table-column prop="address" label="是否有效"></el-table-column>-->
			<el-table-column prop="" label="数据范围" align="center">
				<template slot-scope="scope">
					<span>{{ dsTypeName(scope.row.dsType) }}</span>
				</template>
			</el-table-column>
			<el-table-column prop="" label="创建时间" align="center">
				<template slot-scope="scope">
					<span>{{scope.row.createTime| formeTime}}</span>
				</template>
			</el-table-column>
			<el-table-column fixed="right" label="操作" align="center" width="350">
				<template slot-scope="scope">
					<div class="centered-content">
						<el-tooltip content="编辑" placement="top">
							<el-button @click="editorEvent(scope.row)" type="warning" size="mini" plain><i
									class="iconfont el-icon-edit"></i></el-button>
						</el-tooltip>
						<el-tooltip content="删除" placement="top">
							<el-button @click="deleteUserEvent(scope.row)" type="danger" size="mini" plain><i
									class="iconfont el-icon-delete"></i></el-button>
						</el-tooltip>
						<el-tooltip content="授权权限" placement="top">
							<el-button @click="authorizationMenu(scope.row)" type="primary" size="mini" plain><i
									class="iconfont iconshouquancaidan"></i></el-button>
						</el-tooltip>
					</div>
					<!-- <el-tooltip content="授权用户"
                      placement="top">
            <el-button @click="distributionUserEvent(scope.row)"
                       type="primary"
                       size="mini"
                       plain><i class="iconfont iconfenpeiyonghu"></i></el-button>
          </el-tooltip> -->
				</template>
			</el-table-column>
		</el-table>
		<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage"
			:page-size=pageSize layout="total, sizes, prev, pager, next, jumper" :total=totalPage>
		</el-pagination>

		<!--  新增/编辑 角色-->
		<el-dialog :title="arrDialogTitle[dialogType]" :visible.sync="dialogVisible" :close-on-click-modal="false"
			:close-on-press-escape="false" width="60%" :before-close="handleClose">
			<el-form ref="roleForm" :model="roleForm" label-width="80px" :rules="rules">
				<el-form-item label="角色名称" prop="name">
					<el-input v-model="roleForm.name" placeholder="请输入角色名称"></el-input>
				</el-form-item>
				<el-form-item label="编码" prop="code">
					<el-input v-model="roleForm.code" placeholder="请输入编码"></el-input>
				</el-form-item>
				<el-form-item label="数据权限" prop="dsType">
					<el-select v-model="roleForm.dsType" placeholder="请选择数据权限">
						<el-option v-for="item in arrDsType" :key="item.value" :label="item.label" :value="item.value">
						</el-option>
					</el-select>
				</el-form-item>
				<el-form-item label="描述" prop="describe">
					<el-input type="textarea" v-model="roleForm.describe" placeholder="请输入描述" maxlength="1000"
						show-word-limit></el-input>
				</el-form-item>
			</el-form>
			<span slot="footer" class="dialog-footer">
				<el-button @click="dialogVisible = false">取 消</el-button>
				<el-button type="primary" @click="dialogSubmit('roleForm')">确 定</el-button>
			</span>
		</el-dialog>

		<!--  角色分配功能权限-->
		<div v-if="dialogTreeVisible">
			<el-dialog title="角色分配功能权限" :visible.sync="dialogTreeVisible" width="80%" :lock-scroll="true"
				:close-on-click-modal="false" :close-on-press-escape="false" :before-close="handleClose">
				<el-form class="config-authority" label-width="120px" label-suffix=":">
					<el-form-item label="选择角色模版">
						<el-col :span="21">
							<el-form-item>
								<el-select v-model="ownerRole" multiple clearable placeholder="请选择角色模版">
									<el-option v-for="item in roleList" :key="item.templateId"
										:label="item.templateName" :value="item.templateId">
									</el-option>
								</el-select>
							</el-form-item>
						</el-col>
						<el-col :span="1" style="margin-left: 14px">
							<el-form-item>
								<el-button type="primary" plain @click="updateAuthority">加载资源</el-button>
							</el-form-item>
						</el-col>
					</el-form-item>
					<el-form-item label="资源搜索">
						<el-input v-model="filterText" clearable></el-input>
					</el-form-item>
				</el-form>

				<div class="resource-block">
					<el-tree ref="space" :data="resourceArray" :show-checkbox="true" node-key="id"
						:default-expand-all="true" :props="props" :check-strictly="true"
						:default-checked-keys="accreditKeys" :filter-node-method="filterNode"
						@check-change="handleMenuChange">
						<div class="custom-tree-node" slot-scope="{ node, data }">
							<p>名称：{{data.label}}</p>
							<p>描述：{{data.describe}}</p>
						</div>
					</el-tree>
				</div>
				<span slot="footer" class="dialog-footer">
					<el-button @click="cancelEvent">取 消</el-button>
					<el-button type="primary" @click="postAuthorityBatchFn">确 定</el-button>
				</span>
			</el-dialog>
		</div>
	</div>


</template>

<script>
	import {
		getRoleCon,
		insertRole,
		editorRole,
		deleteRole,
		getAuthorityResourceList,
		getRoledAuthorityResourceList,
		postAuthorityBatch,
		getRoleTemplate,
		getRoleTemplateBatch,
		getMenuList,
		selRoleResource
	} from '@/api/admin.api'
	import moment from "moment";
	export default {
		name: 'role',
		components: {},
		data() {
			return {
				searchData: {},
				// 表格数据
				tableData: [],
				currentPage: 1,
				pageSize: 10,
				totalPage: 0,
				arrDsType: [{
						label: '个人',
						value: '1'
					},
					{
						label: '自定义',
						value: '2'
					},
					{
						label: '本级',
						value: '3'
					},
					{
						label: '本级以及子级',
						value: '6'
					},
					{
						label: '全部',
						value: 9
					}
				],
				dialogTitle: '',
				dialogVisible: false,
				arrDialogTitle: ['新增角色', '编辑角色'],
				dialogType: 0, // 0 新增， 1编辑
				roleForm: {},
				rules: {
					name: [{
						required: true,
						message: '请输入角色名称',
						trigger: 'blur'
					}],
					describe: [{
						required: true,
						message: '请输入描述',
						trigger: 'blur'
					}],
					code: [{
						required: true,
						message: '请输入编码',
						trigger: 'blur'
					}],
					dsType: [{
						required: true,
						message: '请选择编码',
						trigger: 'change'
					}]
				},
				roleId: '', // 角色ID
				resourceArray: [],
				treeList: [], //资源数据列表
				dialogTreeVisible: false,
				props: {
					label: function(data, node) {
						return data.label + data.path
					},
					children: 'children'
				},
				dataObjById: {},
				accreditKeys: [], // 授权资源ID
				primaryIds: [], // 角色原生拥有的权限数据
				filterText: '',
				ownerRole: [], // 选择拥有角色
				roleList: []
			}
		},
		watch: {
			filterText(val) {
				this.$refs.space.filter(val)
			}
		},
		filters: {
			formeTime(val) {
				return val ? moment(val).format('YYYY-MM-DD HH:mm:ss') : ' '
			}
		},
		computed: {
			dsTypeName() {
				return function(dsType) {
					let name = ''
					this.arrDsType.forEach(item => {
						if (item.value === dsType) {
							name = item.label
							return false
						}
					})
					return name
				}
			},
			// 表格高度
			maxHeightNow() {
				const height = window.innerHeight
				return height - 300
			}
		},
		created() {
			// 角色授权菜单
			this.getResourceListFn()
		},
		mounted() {
			// 查询角色列表
			this.getRoleConList()
			// 获取角色选项
			// this.getRoleTemplateFn()
		},
		methods: {
			/**
			 * @description
			 * @author 穆宏宇
			 * @date 2020-11-12 10:42:59
			 * @param
			 * @return
			 * */
			updateAuthority() {
				if (this.ownerRole.length === 0) {
					this.$message({
						type: 'warning',
						message: '请选择角色模版!'
					})
					return
				}
				const self = this
				this.$confirm('选中的角色模版将会覆盖当前角色的资源, 是否继续?', '提示', {
					confirmButtonText: '确定',
					cancelButtonText: '取消',
					type: 'warning'
				}).then(() => {
					// 查询授权资源
					getRoleTemplateBatch({
						ids: self.ownerRole,
						action: 'Get'
					}).then(res => {
						const ids = res.map(item => item.id)
						// 合并资源
						// const tempArr = [...self.accreditKeys,...ids]
						// self.accreditKeys = self.unique(tempArr)
						self.accreditKeys = ids
					})
				}).catch(() => {
					self.ownerRole = []
				})
			},
			/**
			 * @description 权限ID过滤重复
			 * @author 穆宏宇
			 * @date 2020-11-12 11:07:30
			 * @param
			 * @return
			 * */
			unique(arr) {
				let hash = []
				for (let i = 0; i < arr.length; i++) {
					if (hash.indexOf(arr[i]) == -1) {
						hash.push(arr[i])
					}
				}
				return hash
			},
			/**
			 * @description 获取角色选项
			 * @author 穆宏宇
			 * @date 2020-11-12 09:16:10
			 * @param
			 * @return
			 * */
			getRoleTemplateFn() {
				getRoleTemplate().then(res => {
					this.roleList = res
				})
			},
			//优化之后的代码 不管有几级都可以适用,不过用了递归
			filterNode(value, data, node) {
				if (!value) {
					return true
				}
				let _array = [] //这里使用数组存储 只是为了存储值。
				this.getReturnNode(node, _array, value)
				let result = false
				_array.forEach(item => {
					result = result || item
				})
				return result
			},
			getReturnNode(node, _array, value) {
				let isPass = node.data && node.data.label && node.data.label.indexOf(value) !== -1
				isPass ? _array.push(isPass) : ''
				if (!isPass && node.level != 1 && node.parent) {
					this.getReturnNode(node.parent, _array, value)
				}
			},
			/**
			 * @description 查询用户授权列表
			 * @author 穆宏宇
			 * @date 2020-09-28 08:52:28
			 * @param
			 * @return
			 * */
			getResourceListFn() {
				const id = this.$tools.localRead('userId')
				selRoleResource().then(res => {
					//  获取不包含授权资源名称为空的数据
					// let arrayLabel = res.filter(item => item.label)

					let resList = res
					this.treeList = [...res] // arrayLabel
					let dataArr = []
					resList.forEach(item => {
						item['visible'] = false
						item['label'] = `${item.label}（ ${item.path} ）`
						dataArr.push(item)
					})
					// 按照id的顺序重新排列
					dataArr.map(item => {
						this.dataObjById[item['id']] = item
					})
					this.resourceArray = this.getTreeData2(dataArr, ['0', null])
				})
			},
			/**
			 * @description 递归转树型
			 * @author 穆宏宇
			 * @date 2020-09-28 10:40:59
			 * @param data 树型列表
			 * @param defaultRoot 0/null 为跟节点
			 * @param parent 父节点
			 * @return
			 * */
			getTreeData2(data, parent = []) {
				let self = this
				var tree = []
				var temp
				// 遍历数组，通过parentId，获取父节点对象，如果不存在，则为根节点
				data.map(item => {
					if (parent.indexOf(item.parentId) > -1) {
						temp = self.getTreeData2(data, [item.id])
						// 插入子节点数组children
						if (temp.length > 0) {
							item.children = temp
						} else {
							item.children = []
						}
						// 插入父节点对象parent
						if (self.dataObjById[item.parentId]) {
							let {
								id,
								label,
								parentId
							} = self.dataObjById[item.id]
							item.parent = {
								id,
								label,
								parentId
							};
						} else {
							item.parent = {};
						}
						tree.push(item)
					}
				})
				return tree
			},
			/**
			 * @description 输入框清空值
			 * @author 穆宏宇
			 * @date 2020-09-27 16:24:24
			 * @param
			 * @return
			 * */
			searchValue(value) {
				if (!value) {
					this.searchData = {}
				}
			},
			/**
			 * @description 查询权限内的角色
			 * @author 穆宏宇
			 * @date 2020-09-27 15:02:41
			 * @param
			 * @return
			 * */
			getRoleConList() {
				const params = {
					pageSize: this.pageSize,
					pageNum: this.currentPage,
					name: this.searchData.name
				}
				getRoleCon(params).then(res => {
					this.tableData = res.rows
					this.totalPage = res.total
				})
			},
			/**
			 * @description 搜索
			 * @author 穆宏宇
			 * @date 2020-09-24 16:06:16
			 * @param
			 * @return
			 * */
			onSearch() {
				// 查询角色列表
				this.getRoleConList()
			},
			/**
			 * @description 重置
			 * @author 穆宏宇
			 * @date 2020-09-24 16:06:06
			 * @param
			 * @return
			 * */
			resetForm(formName) {
				this.searchData = {}
				this.$refs[formName].resetFields()
			},
			// 每页显示条数
			handleSizeChange(val) {
				this.pageSize = val
				// 查询角色列表
				this.getRoleConList()
			},
			// 当前页
			handleCurrentChange(val) {
				this.currentPage = val
				// 查询角色列表
				this.getRoleConList()
			},
			/**
			 * @description 角色下已分配的用户
			 * @author 穆宏宇
			 * @date 2020-09-27 13:33:46
			 * @param
			 * @return
			 * */
			distributionUserEvent(row) {
				this.$router.push({
					path: '/distribution-users',
					query: {
						id: row.id
					}
				})
			},
			// 关闭弹窗
			handleClose(done) {
				this.accreditKeys = []
				this.filterText = ''
				this.ownerRole = []
				done();
			},
			// 取消
			cancelEvent() {
				this.accreditKeys = []
				this.filterText = ''
				this.ownerRole = []
				this.dialogTreeVisible = false

			},
			/**
			 * @description 角色批量
			 * @author 穆宏宇
			 * @date 2020-09-28 16:00:08
			 * @param
			 * @return
			 * */
			postAuthorityBatchFn() {
				// key 授权id value 授权类型
				var that = this;
				let authorityIds = {}
				// 根据id查找授权类型
				that.accreditKeys.forEach(value => {
					that.treeList.forEach(item => {
						if (value === item.id) {
							authorityIds[item.id] = item.authority
						}
					})
				})
				const data = {
					id: that.roleId,
					authorityIds: authorityIds
				}
				debugger
				postAuthorityBatch(data).then(res => {
					that.$message({
						type: 'success',
						message: '授权成功!'
					})
					that.filterText = ''
					that.ownerRole = []
					that.dialogTreeVisible = false
				})
			},
			/**
			 * @description 新增角色弹窗
			 * @author 穆宏宇
			 * @date 2020-09-27 15:52:36
			 * @param
			 * @return
			 * */
			insertRoleEvent() {
				this.roleForm = {}
				this.dialogVisible = true
				this.dialogType = 0
			},
			/**
			 * @description 编辑角色弹窗
			 * @author 穆宏宇
			 * @date 2020-09-27 16:00:05
			 * @param
			 * @return
			 * */
			editorEvent(row) {
				this.dialogVisible = true
				this.dialogType = 1
				this.roleForm = row
				this.roleId = row.id
			},
			/**
			 * @description 删除角色
			 * @author 穆宏宇
			 * @date 2020-09-27 16:17:08
			 * @param
			 * @return
			 * */
			deleteUserEvent(row) {
				this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
					confirmButtonText: '确定',
					cancelButtonText: '取消',
					type: 'warning'
				}).then(() => {
					deleteRole(row).then(res => {
						this.$message({
							type: 'success',
							message: '删除成功!'
						});
						// 查询角色列表
						this.getRoleConList()
					})

				}).catch(() => {
					this.$message({
						type: 'info',
						message: '已取消删除'
					})
				})
			},
			/**
			 * @description 初始化资源授权为未选项
			 * @author 穆宏宇
			 * @date 2020-10-28 17:38:09
			 * @param
			 * @return
			 * */
			initResource(obj, self) {
				if ('children' in obj) {
					obj.children.forEach(item => {
						item['visible'] = false
						self.initResource(item, self)
					})
				}
			},
			/**
			 * @description 授权菜单
			 * @author 穆宏宇
			 * @date 2020-09-28 08:39:31
			 * @param
			 * @return
			 * */
			authorizationMenu(row) {
				let self = this
				self.roleId = row.id
				// 初始化资源授权为未选项
				self.resourceArray.forEach(item => {
					item['visible'] = false
					self.initResource(item, self)
				})
				// 获取资源授权项
				getRoledAuthorityResourceList({
						roleId: row.id
					})
					.then(res => {
						// 筛查label不为空的数据
						let arrayLabel = res.filter(item => item.label)
						// 提交授权id的集合 (包含选中叶子节点的跟节点id集合)
						self.accreditKeys = this.primaryIds = arrayLabel.map(item => item.id)
						self.dialogTreeVisible = true
					})
					.catch(() => {
						self.$forceUpdate()
						self.dialogTreeVisible = true
					})
			},
			// 提交表单
			dialogSubmit(formName) {
				// 验证表单
				this.$refs[formName].validate((valid) => {
					if (!valid) {
						return false
					}
				})

				// 新增角色
				if (this.dialogType === 0) {
					insertRole(this.roleForm).then(res => {
						this.$message({
							type: 'success',
							message: '添加成功!'
						});
						// 查询角色列表
						this.getRoleConList()
						this.dialogVisible = false
					})
				}
				// 编辑角色
				if (this.dialogType === 1) {
					this.roleForm.id = this.roleId
					const id = this.$tools.localRead('userId')
					editorRole(this.roleForm, id).then(res => {
						this.$message({
							type: 'success',
							message: '编辑成功!'
						});
						// 查询角色列表
						this.getRoleConList()
						this.dialogVisible = false
					})
				}
			},
			/**
			 * @description 菜单授权数据
			 * @author 穆宏宇
			 * @date 2020-10-28 15:28:05
			 * @param
			 * @return
			 * */
			handleMenuChange(data, val) {
				if (val) {
					this.accreditKeys.push(data.id)
				} else {
					this.accreditKeys.splice(this.accreditKeys.indexOf(data.id), 1)
				}
			},
		}
	}
</script>

<style scoped lang="scss">
	.page-box {
		padding: 20px;
		background: white;

		.form-operation {
			text-align: right;

			.el-form-item {
				margin-right: 0;
			}
		}

		.el-pagination {
			padding: 20px;
			text-align: right;
		}

		&-tool {
			text-align: right;
			padding-bottom: 20px;
		}
	}

	.config-authority {
		::v-deep .el-select {
			width: 100%;
		}
	}

	.bigDiv {
		height: calc(100vh - 120px);
	}

	::v-deep .el-tree-node__content {
		height: 100%;
	}

	.custom-tree-node {
		position: relative;
		height: 40px;
		padding: 10px 0;
		display: flex;
		flex-direction: column;
	}

	::v-deep.el-dialog {
		display: flex;
		flex-direction: column;
		margin: 0 !important;
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		max-width: calc(100% - 30px);
	}

	.resource-block {
		max-height: 500px;
		overflow-y: auto;
	}
	.centered-content {
		display: flex;
		justify-content: center;
		align-items: center;
	}
</style>